/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.wechat.api;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.github.panchitoboy.shiro.wechat.repository.UserInfo;
import com.github.panchitoboy.shiro.wechat.repository.WechatTokenResponse;
import com.github.panchitoboy.shiro.wechat.repository.WechatUserRepository;
import com.thinkgem.jeesite.common.config.Config;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.config.GlobalConst;
import com.thinkgem.jeesite.common.persistence.ResponseResult;
import com.thinkgem.jeesite.common.utils.CacheUtils;
import com.thinkgem.jeesite.common.utils.CaptchaUtils;
import com.thinkgem.jeesite.common.utils.PhoneUtils;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.bus.entity.UserOpenid;
import com.thinkgem.jeesite.modules.bus.service.UserOpenidService;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.UserService;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import com.thinkgem.jeesite.modules.wechat.service.MemberUserService;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;

/**
 * 会员及用户登录api
 *
 * @author waile23
 * @version 2018-01-14
 */
@RestController
@RequestMapping(value = "${wechatPath}/rest/crm")
public class WechatUserApiController extends BaseController {
	@Autowired
	private MemberUserService memberUserService;
	@Autowired
	private WechatUserRepository wechatUserRepository;
	@Autowired
	private UserOpenidService userOpenidService;
	@Autowired
	private UserService userService;

	/**
	 * 登录请求，真正登录的POST请求由Filter完成（拦截器验证通过后进入本方法）
	 * 请求 传入参数格式{"phoneNumber":"13888888888", "captcha":"0000", "code": "1234567890"}
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "login", method = RequestMethod.POST)
	public ResponseResult login(HttpServletRequest request, HttpServletResponse response, Model model) {
		UserInfo userInfo = null;
		try{
			Subject subject = SecurityUtils.getSubject();
			userInfo = (UserInfo)subject.getPrincipal();
		}catch (UnavailableSecurityManagerException e) {
			return ResponseResult.failure("获得用户信息时出现错误！");
		}catch (InvalidSessionException e){
			return ResponseResult.failure("获得用户信息时出现错误！");
		}
		//如果没有用户信息返回错误
		if(userInfo == null) {
			return ResponseResult.failure("没有用户信息！");
		}
		//如果是微信模式，取得微信和手机号关联信息
		if(Config.isWechatMode()) {
			// 如果已经登录，则跳转到管理首页
			UserOpenid userOpenid = userOpenidService.getByLoginName(userInfo.getUsername());
			//如果是首次登录，则进行绑定操作
			if(userOpenid == null) {
				try {
					userOpenidService.saveOnLogin(userInfo.getUsername(), userInfo.getOpenId());
				} catch(Exception e) {
					return ResponseResult.failure("关联手机号时出现错误：" + e.getMessage());
				}
			} else {
				try {
					//如果已经登录过，但是不是同一个微信号，那么更新新的微信号
					if(!userOpenid.getOpenid().equals(userInfo.getOpenId())) {
						userOpenid.setOpenid(userInfo.getOpenId());
					}
					//每次登录时都保存一下用户信息
					userOpenidService.save(userOpenid);
				} catch(Exception e) {
					return ResponseResult.failure("关联手机号时出现错误：" + e.getMessage());
				}
			}
		}
		//返回到前台
		WechatTokenResponse wechatTokenResponse = wechatUserRepository.createToken(userInfo);
        Map<String, Object> results = new HashMap<String, Object>();
		results.put("userInfo", userInfo);
		results.put("token", wechatTokenResponse.getToken());
		User user=userService.getByLoginName(userInfo.getUsername());
		results.put("principal", user);
		results.put("runMode", Config.getRunMode());
        return ResponseResult.success(results);
	}
	/**
	 * 退出操作（取消关联）
	 * @param userId
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "loginOut/{userId}", method = RequestMethod.GET)
	public ResponseResult loginOut(@PathVariable("userId") String userId, HttpServletRequest request, HttpServletResponse response, Model model) {
		if(Config.isWechatMode()) {
			User user = UserUtils.getUser();
			String loginName = user.getLoginName();
			UserOpenid userOpenid = userOpenidService.getByLoginName(loginName);
			if(userOpenid != null) {
				userOpenidService.deletePhoneOpenid(userOpenid);
			}
		}
        return ResponseResult.success();
	}

	/**
	 * 在使用微信时，通过code获得用户信息并刷新Token
	 * @param code
	 * @param request
	 * @param response
	 * @return
	 * @throws WxErrorException
	 * @throws IOException
	 */
	@RequestMapping(value = "/userInfo/{code}", method = RequestMethod.GET)
    public ResponseResult getUserInfo(@PathVariable("code") String code, HttpServletRequest request, HttpServletResponse response) throws WxErrorException, IOException {
		//如果缓存中没有内容
		if(CacheUtils.get(GlobalConst.WECHAT_USER_CACHE, code) == null) {
			return ResponseResult.failure("微信验证码错误，请您重新登录！");
		}
		//在缓存中获得openId
		String openId = CacheUtils.get(GlobalConst.WECHAT_USER_CACHE, code).toString();

		//获得用户信息
		UserInfo userInfo = memberUserService.getUserInfo(openId);

		if(userInfo == null) {
			return ResponseResult.failure("您的微信没有和手机号绑定，请您先登录！");
		}
		//创建前端token
		WechatTokenResponse wechatTokenResponse = wechatUserRepository.createToken(userInfo);
		//返回数据
        Map<String, Object> results = new HashMap<String, Object>();
		results.put("userInfo", userInfo);
		results.put("token", wechatTokenResponse.getToken());
		User user=userService.getByLoginName(userInfo.getUsername());
		results.put("principal", user);
		results.put("runMode", Config.getRunMode());
        return ResponseResult.success(results);
    }


	/**
	 * 取得微信用户信息
	 * @param openId
	 * @param request
	 * @param response
	 * @return
	 * @throws WxErrorException
	 * @throws IOException
	 */
	@RequestMapping(value = "/wxMpUser/{openId}", method = RequestMethod.GET)
    public ResponseResult getWxMpUser(@PathVariable("openId") String openId, HttpServletRequest request, HttpServletResponse response) throws WxErrorException, IOException {
		if(StringUtils.isBlank(openId)) {
			return ResponseResult.failure("没有openid！");
		}

		WxMpUser wxMpUser = (WxMpUser)CacheUtils.get(GlobalConst.WECHAT_USER_CACHE, openId);

        return ResponseResult.success(wxMpUser);
    }

	/**
	 * @author Zhang Xingliang
	 * @description 在使用微信时，通过code获得用户信息并刷新Token
	 * @date 16:03 2019/9/29
	 * @param [code, request, response]
	 * @return com.thinkgem.jeesite.common.persistence.ResponseResult
	 **/
	@RequestMapping(value = "/wxUserInfo/{code}", method = RequestMethod.GET)
	public ResponseResult getWxUserInfo(@PathVariable("code") String code, HttpServletRequest request, HttpServletResponse response) throws WxErrorException, IOException {
		//如果缓存中没有内容
		if(CacheUtils.get(GlobalConst.WECHAT_USER_CACHE, code) == null) {
			return ResponseResult.failure("微信验证码错误，请您重新登录！");
		}
		//在缓存中获得openId
		String openId = CacheUtils.get(GlobalConst.WECHAT_USER_CACHE, code).toString();

		if(StringUtils.isBlank(openId)) {
			return ResponseResult.failure("没有openid！");
		}

		WxMpUser wxMpUser = (WxMpUser)CacheUtils.get(GlobalConst.WECHAT_USER_CACHE, openId);

		//获得用户信息
		UserInfo userInfo = new UserInfo() ;

		userInfo.setOpenId(wxMpUser.getOpenId());

		//创建前端token
		//WechatTokenResponse wechatTokenResponse = wechatUserRepository.createToken(userInfo);
		//返回数据
		Map<String, Object> results = new HashMap<String, Object>();
		results.put("userInfo", userInfo);
		results.put("token", wxMpUser.getOpenId());
//		User user=userService.getByLoginName(userInfo.getUsername());
		results.put("principal", wxMpUser);
		results.put("runMode", Config.getRunMode());
		return ResponseResult.success(results);
	}

}
